package com.fire.control.system.module.notice.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fire.control.system.config.getui.GetuiManager;
import com.fire.control.system.config.quartz.QuartzManager;
import com.fire.control.system.config.redis.RedisService;
import com.fire.control.system.dto.GetuiDto;
import com.fire.control.system.dto.MessageUserDto;
import com.fire.control.system.dto.NoticeDTO;
import com.fire.control.system.dto.SelectGroupDTO;
import com.fire.control.system.dto.SelectRoleDTO;
import com.fire.control.system.dto.UserDTO;
import com.fire.control.system.entity.Company;
import com.fire.control.system.entity.DeviceGroup;
import com.fire.control.system.entity.Notice;
import com.fire.control.system.entity.NoticeDetail;
import com.fire.control.system.entity.Role;
import com.fire.control.system.entity.User;
import com.fire.control.system.job.NoticeJob;
import com.fire.control.system.module.company.dao.CompanyMapper;
import com.fire.control.system.module.company.service.CompanyService;
import com.fire.control.system.module.device.dao.DeviceGroupMapper;
import com.fire.control.system.module.device.service.impl.DeviceServiceImpl;
import com.fire.control.system.module.notice.dao.NoticeDetailRepository;
import com.fire.control.system.module.notice.dao.NoticeMapper;
import com.fire.control.system.module.notice.service.NoticeService;
import com.fire.control.system.module.role.dao.RoleMapper;
import com.fire.control.system.module.user.dao.UserMapper;
import com.fire.control.system.statics.Message_Response;
import com.fire.control.system.statics.ResponseMessage;
import com.fire.control.system.statics.Status_Message;
import com.fire.control.system.support.protocol.comman.ProtocolSelector;
import com.fire.control.system.support.protocol.comman.ResponseProtocol;
import com.fire.control.system.support.protocol.notice.NoticeRequestProtocol;
import com.fire.control.system.support.util.ResultPageUtil;
import com.fire.control.system.support.util.SmsUtil;
import com.fire.control.system.support.util.XdaoDate;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

/**
 * 
 * @ClassName:  NoticeServiceImpl
 * @Description:  消息通知服务接口具体实现
 * @author:  xiechengguang
 * @date:  2017年6月9日 下午7:00:44
 *
 */
@Service("noticeService")
public class NoticeServiceImpl implements NoticeService {
	
	@Autowired private NoticeMapper noticeMapper;
	@Autowired private ProtocolSelector protocolSelector;
	@Autowired private CompanyMapper companyMapper;
	@Autowired private UserMapper userMapper;
	@Autowired private DeviceGroupMapper deviceGroupMapper;
	@Autowired private NoticeDetailRepository noticeDetailRepository;
	@Autowired private RoleMapper roleMapper;
	@Autowired private QuartzManager quartzManager;
	@Autowired private GetuiManager getuiManager;
	@Autowired private SmsUtil loginUtil;
	@Autowired private RedisService redisService;
	@Autowired private CompanyService companyService;
	
	private static final Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class);
	private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
	
	
	/**
	 * <p>Author: xiechengguang</p> 
	 * <p>Title: getNoticeList</p> 
	 * <p>Description: 获取消息通知列表，分页显示</p> 
	 * @param request
	 * @return 
	 * @see com.fire.control.system.module.notice.service.NoticeService#getNoticeList(com.fire.control.system.support.protocol.notice.NoticeRequestProtocol)
	 */
	@Override
	public ResponseProtocol getNoticeList(NoticeRequestProtocol request, UserDTO user) {
		ResponseProtocol respProtocol = protocolSelector.choose(request);
		String companyId = user.getCompany().getId();
		int page = request.getCurrentPage();
		int size = request.getPageSize();
		PageHelper.startPage(page, size);
		Company company = companyMapper.getById(request.getCompanyId());
		
		List<NoticeDTO> noticeList = noticeMapper.getAllByCompanyId(companyId);
		
		if(noticeList != null && !noticeList.isEmpty()) {
			for(NoticeDTO n : noticeList) {
				String noticeId = n.getId();
				/**获取发送对象*/
				List<SelectRoleDTO> roles = noticeMapper.getRolesByNoticeId(noticeId);
				if(roles != null && !roles.isEmpty()) {
					String sendObject="";
					for(SelectRoleDTO r : roles) {
						sendObject = r.getName();
						sendObject += ",";
					}
					sendObject = sendObject.substring(0, sendObject.length()-1);
					n.setSendObject(sendObject);
				}
				/**获取设备组*/
				List<SelectGroupDTO> groups = noticeMapper.getGroupsByNoticeId(noticeId);
				if(groups != null && !groups.isEmpty()) {
					String sendGroup="";
					for(SelectGroupDTO g : groups) {
						sendGroup = g.getGroupName();
						sendGroup += ",";
					}
					sendGroup = sendGroup.substring(0, sendGroup.length()-1);
					n.setSendObject(sendGroup);
				}	
					
			}
			
			ResponseMessage.CODE_200.messageToProtocol(respProtocol);
			respProtocol.setData(ResultPageUtil.resultPage(new PageInfo<NoticeDTO>(noticeList), noticeList));
			return respProtocol;
		}
		ResponseMessage.CODE_204.messageToProtocol(respProtocol);
		respProtocol.setData(null);
		return respProtocol;
	}
	
	public Date stringToDate(String strdate) {
		
		try {
			return format.parse(strdate);
		} catch (ParseException e) {
			logger.info("日期转换错误");
		}
		return new Date();
	}
	
	
	
	/**
	 * <p>Author: xiechengguang</p> 
	 * <p>Title: addNotice</p> 
	 * <p>Description: 添加消息通知  </p> 
	 * @param request
	 * @return 
	 * @see com.fire.control.system.module.notice.service.NoticeService#addNotice(com.fire.control.system.support.protocol.notice.NoticeRequestProtocol)
	 */
	@Transactional
	@Override
	public ResponseProtocol addNotice(NoticeRequestProtocol request, UserDTO ue) {
		ResponseProtocol respProtocol = protocolSelector.choose(request);
		Notice notice = new Notice();
		
		//通过公司id查找到公司
//		String companyId = ue.getCompany().getId();
		
		String companyId = request.getCompanyId();
		Company company = companyMapper.getById(companyId);
		notice.setCompany(company);
		
		notice.setTitle(request.getTitle());
		notice.setContent(request.getContent());
		
		if(request.getSendTime() != null ) {
			notice.setSendTime(this.stringToDate(request.getSendTime()));
		}
		if(request.getValidTime() != null ) {
			notice.setValidTime(this.stringToDate(request.getValidTime()));
		}
		// 发送者（默认为当前登录用户）
		User user = userMapper.getById(ue.getUserId());
		notice.setUser(user);
		
		// 创建对象后就已生成noticeId
		String noticeId = notice.getId();
		
		// 根据角色id获取角色（发送对象）
		String[] roleIds = request.getRoleIds();
		List<Role> roles = new ArrayList<Role>();
		for(String roleId : roleIds) {
			noticeMapper.saveNoticeRole(roleId, noticeId); //保存通知-角色关系表数据
			Role role = roleMapper.findById(roleId);
			roles.add(role);
		}
		notice.setRoles(roles);
		
		// 设备组
		String[] groupIds = request.getGroupIds();
		List<DeviceGroup> groups = new ArrayList<DeviceGroup>();
		for(String groupId : groupIds) {
			noticeMapper.saveNoticeGroup(groupId, noticeId);  //保存通知-设备组关系表数据
			DeviceGroup deviceGroup = deviceGroupMapper.findById(groupId);
			groups.add(deviceGroup);
		}
		notice.setDeviceGroups(groups);
		
		noticeMapper.addNotice(notice);
		
		// TODO 根据角色id + 企业id 定位到底发给哪些人
		List<User> userList = userMapper.getUsers(roleIds, companyId);
		
		for(User u : userList) {
			NoticeDetail detail = new NoticeDetail(); // 保存通知详细
			detail.setTitle(request.getTitle());
			detail.setNoticeContent(request.getContent());
			detail.setNotice(notice);
//			detail.setReciveTime(new XdaoDate()); //TODO 当某个业务比如email送达返回后，即为接收时间，再修改此时间
			detail.setUser(u);
			noticeDetailRepository.save(detail);
		}
		
		//开始启动定时发送(定时时间大于等于当前系统时间)
		if(notice.getSendTime()!=null && notice.getSendTime().getTime() >= System.currentTimeMillis())
		{
			quartzManager.execute(notice.getId(),NoticeJob.class, XdaoDate.dateToCron(notice.getSendTime()));
		} else { //立即发送
			sendNoticeDetail(noticeId);
		}
		
		ResponseMessage.CODE_200.messageToProtocol(respProtocol);
		respProtocol.setData(noticeId);
		return respProtocol;
	}
	
	//定时器会调用此方法
	public void sendNoticeDetail(String noticeId){
		Notice notice = noticeMapper.getById(noticeId); 
		
		//根据消息ID 获取 具体发送的用户List
		List<MessageUserDto> uList = userMapper.getSendUsersByNoticeId(noticeId); 
		//循环用户列表
		for(MessageUserDto msgUserDto : uList) {
			String phone = msgUserDto.getTel();
			String cid = msgUserDto.getCid();
			
			String userId = msgUserDto.getUserId();
			// 根据通知id和用户id获取 通知详细
			// 根据通知id获取通知明细
			NoticeDetail noticeDetail = noticeDetailRepository.getByNoticeIdAndUserId(noticeId, userId);
			
			//发送APP
			if(StringUtils.isNotEmpty(cid)){
				//调用个推
				GetuiDto getuiDto = getuiManager.pushNotificationSingle(notice.getTitle(), notice.getContent(), cid);
				String sendStatus = getuiDto.getResult().equals("ok")?Status_Message.success.toString():Status_Message.fail.toString();
				//记录发送状态
				noticeDetailRepository.setSendStatus(sendStatus, noticeDetail.getId());
			}
		}
	}
	
	/**
	 * <p>Author: xiechengguang</p> 
	 * <p>Title: updateNotice</p> 
	 * <p>Description: 修改消息通知</p> 
	 * @param request
	 * @return 
	 * @see com.fire.control.system.module.notice.service.NoticeService#updateNotice(com.fire.control.system.support.protocol.notice.NoticeRequestProtocol)
	 */
	@Transactional
	@Override
	public ResponseProtocol updateNotice(NoticeRequestProtocol request, UserDTO u) {
		ResponseProtocol respProtocol = protocolSelector.choose(request);
		Notice notice = noticeMapper.getById(request.getId());
		
		String companyId = request.getCompanyId();
		Company company = companyMapper.getById(companyId);
		notice.setCompany(company);
		
		notice.setTitle(request.getTitle());
		notice.setContent(request.getContent());
		
		if(request.getSendTime() != null ) {
			notice.setSendTime(this.stringToDate(request.getSendTime()));
		}
		if(request.getValidTime() != null ) {
			notice.setValidTime(this.stringToDate(request.getValidTime()));
		}
		// 发送者
		User user = userMapper.getById(u.getUserId());
		notice.setUser(user);
		
		String noticeId = notice.getId();
		
		//根据角色id获取角色（发送对象）
		String[] roleIds = request.getRoleIds();
		List<Role> roles = new ArrayList<Role>();
		// 先根据noticeId删除所有Role角色，再保存新的关系
		noticeMapper.deleteNoticeRole(noticeId);
		for(String roleId : roleIds) {
			noticeMapper.saveNoticeRole(roleId, noticeId); //保存通知-角色关系表数据
			Role role = roleMapper.findById(roleId);
			roles.add(role);
		}
		notice.setRoles(roles);
		
		// 设备组
		String[] groupIds = request.getGroupIds();
		List<DeviceGroup> groups = new ArrayList<DeviceGroup>();
		// 先根据noticeId删除所有设备组id，再保存新的关系
		noticeMapper.deleteNoticeGroup(noticeId);
		for(String groupId : groupIds) {
			noticeMapper.saveNoticeGroup(groupId, noticeId);  //保存通知-设备组关系表数据
			DeviceGroup deviceGroup = deviceGroupMapper.findById(groupId);
			groups.add(deviceGroup);
		}
		notice.setDeviceGroups(groups);
		
		noticeMapper.updateNotice(notice);
		
		ResponseMessage.CODE_200.messageToProtocol(respProtocol);
		respProtocol.setData(noticeId);
		return respProtocol;
	}
	
	/**
	 * <p>Author: xiechengguang</p> 
	 * <p>Title: deleteNotice</p> 
	 * <p>Description: 删除消息通知，实际上修改status </p> 
	 * @param request
	 * @return 
	 * @see com.fire.control.system.module.notice.service.NoticeService#deleteNotice(com.fire.control.system.support.protocol.notice.NoticeRequestProtocol)
	 */
	@Override
	public ResponseProtocol deleteNotice(NoticeRequestProtocol request) {
		ResponseProtocol respProtocol = protocolSelector.choose(request);
		if(request != null) {
			String[] ids = request.getIds();
			noticeMapper.deleteNoticeByIds(ids);
			ResponseMessage.CODE_200.messageToProtocol(respProtocol);
			return respProtocol;
		}
		ResponseMessage.CODE_400.messageToProtocol(respProtocol);
		return respProtocol;
	}
	
	/**
	 * <p>Author: xiechengguang</p> 
	 * <p>Title: searchNotices</p> 
	 * <p>Description: 根据条件搜索消息通知</p> 
	 * @param request
	 * @return 
	 * @see com.fire.control.system.module.notice.service.NoticeService#searchNotices(com.fire.control.system.support.protocol.notice.NoticeRequestProtocol)
	 */
	@Override
	public ResponseProtocol searchNotices(NoticeRequestProtocol request, UserDTO user) {
		ResponseProtocol respProtocol = protocolSelector.choose(request);
		
		if(request != null) {
			int page = request.getCurrentPage();
			int size = request.getPageSize();
			String companyId = user.getCompany().getId(); // 当前用户所属企业id
			List<String> companyIds = this.companyService.getChildCompanyIdList(companyId);
			request.setCompanyIds(companyIds);
			
			PageHelper.startPage(page, size);
			List<NoticeDTO> noticeList = noticeMapper.searchNotices(request);
			if(noticeList != null && !noticeList.isEmpty()) {
				
				for(NoticeDTO n : noticeList) {
					String noticeId = n.getId();
					//获取发送对象
					List<SelectRoleDTO> roles = noticeMapper.getRolesByNoticeId(noticeId);
					n.setRoles(roles);
					StringBuffer sendObject= new StringBuffer("");
					if(roles != null && !roles.isEmpty()) {
						
						for(SelectRoleDTO r : roles) {
							sendObject.append(r.getName());
							sendObject.append(",");
						}
						n.setSendObject(sendObject.substring(0, sendObject.toString().length()-1));
					}
					
					//获取设备组
					List<SelectGroupDTO> groups = noticeMapper.getGroupsByNoticeId(noticeId);
					n.setGroups(groups);
					StringBuffer sendGroup= new StringBuffer("");
					if(groups != null && !groups.isEmpty()) {
						
						for(SelectGroupDTO g : groups) {
							sendGroup.append(g.getGroupName());
							sendGroup.append(",");
						}
						n.setSendGroup(sendGroup.substring(0, sendGroup.toString().length()-1));	
					}	
					
				}
				respProtocol.setData(ResultPageUtil.resultPage(new PageInfo<NoticeDTO>(noticeList), noticeList));
				return respProtocol;
			}
			ResponseMessage.CODE_204.messageToProtocol(respProtocol);
			return respProtocol;
		}
		ResponseMessage.CODE_400.messageToProtocol(respProtocol);
		return respProtocol;
	}
	
	/**
	 * <p>Author: xiechengguang</p> 
	 * <p>Title: getNoticeInfo</p> 
	 * <p>Description: 获取通知详细</p> 
	 * @param request
	 * @return 
	 * @see com.fire.control.system.module.notice.service.NoticeService#getNoticeInfo(com.fire.control.system.support.protocol.notice.NoticeRequestProtocol)
	 */
	@Override
	public ResponseProtocol getNoticeInfo(NoticeRequestProtocol request) {
		ResponseProtocol respProtocol = protocolSelector.choose(request);
		if(request != null && request.getId() != null) {
			NoticeDTO notice = noticeMapper.getDetailById(request.getId());
			
			if(notice != null ) {
				List<SelectRoleDTO> roles = noticeMapper.getRolesByNoticeId(notice.getId());
				List<SelectGroupDTO> groups = noticeMapper.getGroupsByNoticeId(notice.getId());
				notice.setRoles(roles);
				notice.setGroups(groups);
				
				ResponseMessage.CODE_200.messageToProtocol(respProtocol);
				respProtocol.setData(notice);
				return respProtocol;
			}
		}
		ResponseMessage.CODE_400.messageToProtocol(respProtocol);
		return respProtocol;
		
	}
	
	
}
